﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Xml.Linq;

using DbSharp.Framework.DbObject;



namespace DbSharp.Framework.CaseFile.Parser
{

    /// <summary>
    /// Extract all PerformanceTestCase objects from case file
    /// </summary>
    public class PerfTestCaseExtractor
    {
        #region Private members
        XElement m_PerfTestCasesRootElement = null;
        XElement m_GlobalSettingElement = null;
        IEnumerable<IStatementDeclaration> m_ListStatement;
        List<PerformanceTestCase> m_ListCase = new List<PerformanceTestCase>();
        #endregion


        public PerfTestCaseExtractor(IEnumerable<IStatementDeclaration> listStatement, XElement perfTestCasesRootElement, XElement globalSettingElement)
        {
            if (perfTestCasesRootElement != null)
            {
                if ((listStatement == null) &&
                    (perfTestCasesRootElement.Elements("perfTestCase").Count() > 0))
                    throw new ArgumentNullException("listStatement");
            }

            m_PerfTestCasesRootElement = perfTestCasesRootElement;
            m_GlobalSettingElement = globalSettingElement;
            m_ListStatement = listStatement;
            Extract();
        }

        #region Private methods

   

        private void Extract()
        {
            m_ListCase.Clear();
            if (m_PerfTestCasesRootElement == null)
                return;

            var q = from caseElement in m_PerfTestCasesRootElement.Elements("perfTestCase")
                    let ignoreThisAttribute = caseElement.Attribute("ignoreThis")
                    let testInSandboxAttribute = caseElement.Attribute("testInSandbox")
                    let remarkElement = caseElement.Element("testCaseRemark")
                    let tagsAttr = caseElement.Attribute("tags")
                    select new
                    {
                        TestCaseName = caseElement.Attribute("testCaseName").Value.Trim(),
                        StatementAlias = caseElement.Attribute("statementAlias").Value.Trim(),
                        IgnoreThis = ignoreThisAttribute == null ? false : ignoreThisAttribute.Value.Trim().ToUpper() == "TRUE",
                        TestInSandbox = testInSandboxAttribute == null ? false : testInSandboxAttribute.Value.Trim().ToUpper() == "TRUE",
                        TestRemark = remarkElement == null ? string.Empty : remarkElement.Value,
                        TagsValue = tagsAttr == null ? string.Empty : tagsAttr.Value,
                        InputArgumentsElement = caseElement.Element("inputArguments"),
                        OutputSettingElement= caseElement.Element("outputSetting"),

                        SetupElement = caseElement.Element("setup"),
                        TeardownElement = caseElement.Element("teardown"),
                    };

            foreach (var item in q)
            {
                var caseObj = new PerformanceTestCase(item.TestCaseName, m_ListStatement, item.StatementAlias, item.InputArgumentsElement, m_GlobalSettingElement);
                caseObj.TestCaseRemark = item.TestRemark;
                caseObj.IgnoreThis = item.IgnoreThis;
                caseObj.TestCaseName = item.TestCaseName;
                caseObj.TagsValue = item.TagsValue;
                caseObj.TestInSandbox = item.TestInSandbox;
                OutputSettingAttrParser.OverrideSetting(caseObj.OutputSetting, item.OutputSettingElement);
            
                var setupStatementExtractor = new SetupSectionExtractor(item.TestCaseName, m_GlobalSettingElement, m_ListStatement, item.SetupElement);
                foreach (var action in setupStatementExtractor.ListAction)
                { 
                    caseObj.AddSetupStatement(action);
                }

                var teardownStatementExtractor = new SetupSectionExtractor(item.TestCaseName, m_GlobalSettingElement, m_ListStatement, item.TeardownElement);
                foreach (var action in teardownStatementExtractor.ListAction)
                {
                    caseObj.AddTeardownStatment(action);
                }

                m_ListCase.Add(caseObj);
            }
        }


        #endregion


        #region Public properties/methods

        public ReadOnlyCollection<PerformanceTestCase> ListCase
        {
            get
            {
                return new ReadOnlyCollection<PerformanceTestCase>(m_ListCase);
            }
        }

        public PerformanceTestCase this[string testCaseName]
        {
            get 
            {
                if (string.IsNullOrEmpty(testCaseName))
                    return null;

                string upperCaseName = testCaseName.Trim().ToUpper();
                foreach (var item in m_ListCase)
                {
                    if (item.TestCaseName.Trim().ToUpper() == upperCaseName)
                        return item;
                }
                return null;
            }
        }


        public void TruncateTestCases(int maxCount)
        {
            int startIndex = maxCount;
            if (startIndex > -1)
                m_ListCase.RemoveRange(startIndex, m_ListCase.Count);
        }

        #endregion



    }
}
